#include <stdlib.h>

#include "lib.h"
#include "bjsql.h"
#include "bjopts.h"
#include "bjsaved.h"
#include "bjhand.h"
#include "odbc.h"
#include "bjrules.h"
#include "serv.h"
#include "missinggamenums.h"
#include "bjproto.h"

#define MAXCARDS	32					// max # cards in hand (stored in dbase)

BJSQL::BJSQL
(
	const String&	DBDSN,
	const String&	DBLogin,
	const String&	DBPassword
)
:	TrackSQL(DBDSN, DBLogin, DBPassword)
{
#ifdef USE_MISSINGGAMENUMS
	//missing game nums deleted in TrackSQL::~TrackSQL
	missinggamenums = new MissingGameNums(this, "pub_getTableIdentityBlackjack");
#endif
	resetSavedGame();
}


int32
BJSQL::getMachineOptions( uint8 machid, uint8* ruleSetId, uint8* nDecks, uint8 *nBets )
{
	ODBCConnection*	conn	=NULL;
	ODBCQuery*		query	=NULL;
	int32			result	=NoError;

	*ruleSetId	= 0xff; //nothing
	*nDecks		= 0;

	conn = getConn();
	if (!conn)
	{
		result = NoConnection;
		goto cleanup;
	}

	query = conn->query();
	if (!query)
	{
		result = InitError;
		goto cleanup;
	}

	query->define("exec pub_BJGetMachineOptions ");
	query->addParam(machid);

	if( query->exec() )
		if( query->getRow() )
			if( query->getData(1,ruleSetId) && query->getData(2,nDecks) && query->getData(3,nBets) )
					goto cleanup;

	result = ExecFailed;

cleanup:

	if (query)
		delete query;
	if (conn)
		delete conn;

	return result;

}

int32
BJSQL::getRuleSet
(
	uint8		ruleSetId,
	BJRules*	pRules
)
{
	ODBCConnection*	conn	=NULL;
	ODBCQuery*		query	=NULL;
	int32			result	=NoError;
	BJRules			rules;

	conn = getConn();
	if (!conn)
	{
		result = NoConnection;
		goto cleanup;
	}

	query = conn->query();
	if (!query)
	{
		result = InitError;
		goto cleanup;
	}

	query->define("exec pub_BJGetRuleSet ");
	query->addParam(ruleSetId);
	if (!query->exec())
	{
		result = ExecFailed;
		goto cleanup;
	}

	//broken for the moment
	result = rules.ImportFromQuery( query, ruleSetId );
	if (result != 0)
	{
		result = ExecFailed;
		goto cleanup;
	}

	*pRules = rules;

cleanup:

	if (query)
		delete query;
	if (conn)
		delete conn;

	return result;
}

//psharpless 12/20/06 Case: 16101
int32
BJSQL::getSideBetOptions(uint8 machid, uint8* paytable)
{
	ODBCConnection*	conn	=NULL;
	ODBCQuery*		query	=NULL;
	int32			result	=NoError;

	conn = getConn();
	if (!conn)
	{
		result = NoConnection;
		goto cleanup;
	}

	query = conn->query();
	if (!query)
	{
		result = InitError;
		goto cleanup;
	}

	query->define("exec pub_BJGetSideBetOptions ");
	query->addParam(machid);
    if (query->exec())
    {
        while (query->getRow())
        {
            query->getData(1, paytable);
        }
    }
	else
	{
		result = ExecFailed;
		goto cleanup;
	}

cleanup:

	if (query)
		delete query;
	if (conn)
		delete conn;

	return result;
}

// kharmon.  02-13-07.  #16101.  Added nSideBet amount parameter for new Perfect Pairs sidebet option.		
int32
BJSQL::createGame(int32	casinoId,PID pid,bool8 forMoney,uint8 machid,SESSIONID sessionId,
                  int32 compFactor,char *gid, int32 bet, int32 *pBonusBalanceBet, uint8 iBJBet, 
	              uint8 nBets, char *tieID, int32 nSideBet)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_CreateGameBJ ");
		query->addParam(casinoId);
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid);
		query->addParam(sessionId, ODBCQuery::NOQUOTES);
		query->addParam(compFactor);
		query->addParam(bet, ODBCQuery::MONEY);
		query->addParam(iBJBet);
		query->addParam(nBets);
		query->addParam(tieID, ODBCQuery::NOQUOTES);
        query->addParam(nSideBet, ODBCQuery::MONEY);        // kharmon.  02-13-07.  #16101.  Added for Perfect Pairs.

		if (query->exec())
		{
			if (query->getRow())
            {
				ok = query->getData(1, gid, BJ_GAMEID_SIZE) &&
                     query->getData(2, pBonusBalanceBet, ODBCQuery::MONEY);
            }

			// Flush the recordset

            while (query->getRow());
		}
		delete query;
	}
	delete conn;

	if (ok)
	{

#ifdef USE_MISSINGGAMENUMS
		int32 gamenum = atol(gid);
		if (missinggamenums)
			missinggamenums->setGameNum(gamenum);
#endif

		return NoError;
	}
	else
	{
		gid[0] = '\0';
		return ExecFailed;
	}
}

int32
BJSQL::gameDone
(
	char*	gid
)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJGameDone ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		if (query->exec())
			ok = true;
		delete query;
	}

	delete conn;

	if (ok)
		return NoError;
	else
		return ExecFailed;
}


/**************************************************************************************************************
 * @fn BJSQL::setSideBetResult( char* acGID,uint8 ucState,int32 nPayout,int32 *pnBalance )
 * 
 * This method is called to record the results of the player's side bet, if he made one.
 *
 * @param  acGID     -  (in)  the gamenum that this bet will be associated with in the database.
 * @param  ucState   -  (in)  represents what kind of win or loss the player had, see PerfectPairWinTypes enum.
 * @param  nPayout   -  (in)  money amount of win, zero on loss.
 * @param  pnBalance -  (out) player balance after adjusting for win or loss.
 *
 * kharmon.  02-13-07.  #16101.  Added for new Perfect Pairs sidebet option.
 **************************************************************************************************************/
int32
BJSQL::setSideBetResult( char* acGID,uint8 ucState,int32 nPayout,int32 *pnBalance )
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	*pnBalance = 0;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJSideBet ");
		query->addParam(acGID, ODBCQuery::NOQUOTES);
		query->addParam( (uint8) ucState );
		query->addParam(nPayout, ODBCQuery::MONEY);

		if (query->exec())
		{
			if (query->getRow())
				ok = query->getData(1, pnBalance, ODBCQuery::MONEY);

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}



int32
BJSQL::setInsuranceState( char *gid,uint8 state,int32 payout,int32 *balance )
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	*balance = 0;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJInsure ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam( (uint8)(state != 0) );
		query->addParam(payout, ODBCQuery::MONEY);

		if (query->exec())
		{
			if (query->getRow())
				ok = query->getData(1, balance, ODBCQuery::MONEY);

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
BJSQL::createDealerHand
(
	char*	gid,
	int32		numcards,
	uint8*		cards
)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJNewDealerHand ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(cards, numcards, ODBCQuery::BINARY);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}



int32
BJSQL::saveDealerHand
(
	char*	gid,
	uint8		nCards,
	uint8*		pCards
)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJSaveDealerHand ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(pCards, nCards, ODBCQuery::BINARY);
		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
BJSQL::savePlayerHand( char *gid, uint8 handNum, uint8 nBets,
					  uint8	numcards, uint8* cards, uint8 bet, uint8 hit,
					  uint8	stand, uint8 doubled, uint8	split, uint8 surrender,
					  uint8	raise, uint8 zap,					/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
					  bool8 adjustBalance,	int32* balance,
					  int32* bonusBalanceBet) // In/out parameter -- the value will change only if adjustBalance is 1
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	*balance = 0;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJSavePlayerHand ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(handNum);
		query->addParam(nBets);
		query->addParam(cards, numcards, ODBCQuery::BINARY);
		query->addParam(bet				);
		query->addParam(hit				);
		query->addParam(stand			);
		query->addParam(doubled			);
		query->addParam(split			);
		query->addParam(surrender		);
		query->addParam(raise			);
		/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
		query->addParam(zap);
		query->addParam(adjustBalance	);
		query->addParam(*bonusBalanceBet);

		if (query->exec())
		{
			if (query->getRow())
			{
				ok  = query->getData(1, balance, ODBCQuery::MONEY) &&
					  query->getData(4, bonusBalanceBet, ODBCQuery::MONEY);
			}

			// Flush recordset
			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}


int32
BJSQL::addDealerCards
(
	char *gid,
	int32 numcards,
	uint8* cards
)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJAddDealerCards ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(cards, numcards, ODBCQuery::BINARY);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
BJSQL::setPlayerPayout
(
	char*	gid,
	int32		handNum,
	int32		payout
)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJSetPlayerPayout ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(handNum);
		query->addParam(payout, ODBCQuery::MONEY);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

//  Helper Function
bool8
getSavedHand( ODBCQuery* query, BJSavedGame::_BJBet *sBet, int32 handNum )
{
	int32 bonusBalanceBet = 0;
	uint8 nBets=0;
	bool8 ok = true;

	ok &= query->getData(2, &nBets);
	sBet->hands[handNum].m_nBets = nBets;

	ok &= query->getData(3, sBet->hands[handNum].cards, MAXCARDS, &sBet->hands[handNum].numCards);

	//actions
	uint8 bet;
	uint8 hit;
	uint8 stand;
	uint8 doubled;
	uint8 split;
	uint8 surrender;
	uint8 raise;
	uint8 zap;			/// [2013-07-15] Charles. Added for supporting 'Zappit Rackcard'.

	ok &= query->getData( 4, &bet);
	ok &= query->getData( 5, &hit);
	ok &= query->getData( 6, &stand);
	ok &= query->getData( 7, &doubled);
	ok &= query->getData( 8, &split);
	ok &= query->getData( 9, &surrender);
	ok &= query->getData(10, &raise);
	ok &= query->getData(11, &zap);					/// [2013-07-15] Charles. Added for supporting 'Zappit Rackcard'.
	ok &= query->getData(12, &bonusBalanceBet, ODBCQuery::MONEY);

	sBet->hands[handNum].m_actionBits = 0;

	if (bet)
		sBet->hands[handNum].m_actionBits |= BJF_BET;
	if (hit)
		sBet->hands[handNum].m_actionBits |= BJF_HIT;
	if (stand)
		sBet->hands[handNum].m_actionBits |= BJF_STAND;
	if (doubled)
		sBet->hands[handNum].m_actionBits |= BJF_DOUBLE;
	if (split)
		sBet->hands[handNum].m_actionBits |= BJF_SPLIT;
	if (surrender)
		sBet->hands[handNum].m_actionBits |= BJF_SURRENDER;
	if (raise)
		sBet->hands[handNum].m_actionBits |= BJF_RAISE;
	if (zap) {
		sBet->hands[handNum].m_actionBits |= BJF_ZAP;
	}

	sBet->hands[handNum].bonusBalanceBet = bonusBalanceBet;

	return ok;
}


int32
BJSQL::hasSavedGame(const PID& pid,bool8 forMoney,uint8 machid,BJSavedGame* dest, bool8* exists)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;
    int32 which, totalHands,numHands;
    int32 result = 0;

    numHands = totalHands = 0;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJGetSavedGame ");
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid);

		if (query->exec())
		{
			int16	smallint;
			uint8	tinyint;
			ok = true;

			// game data
			//
			if (query->getRow())
			{
				char	insState[2];
				int32	hasSaved = 0;

				query->getData(1, &hasSaved);

                if (hasSaved==1)
				{
					result = 1;

                    // kharmon.  10-23-06.  #16151.  This is an older saved game, use the old restore code.
                    dest->bHasOriginalShoe = false;
					query->getData(2, &dest->maxBJBets);
					query->getData(3, &dest->nBJBets);
					query->getData(4, &dest->shue.seed);
					query->getData(5, &smallint);
					dest->shue.next = smallint;
					query->getData(6, &dest->numDecks);
					query->getData(7, &tinyint);
					dest->currentHand = tinyint;
					query->getData(8, &dest->currentBJBet);
					query->getData(9, dest->dealerCards, MAXCARDS,	&dest->numDealerCards);

                    query->getData(10, dest->BJBets[0].gid, BJ_GAMEID_SIZE);
                    query->getData(11, &dest->BJBets[0].bet, ODBCQuery::MONEY);
					query->getData(12, &dest->BJBets[0].iBJBet);
                    query->getData(13, &dest->BJBets[0].numPlayerHands );
					query->getData(14, insState, 2 );
					    dest->BJBets[0].m_insuranceState = insState[0];

                    query->getData(15, dest->BJBets[1].gid, BJ_GAMEID_SIZE);
                    query->getData(16, &dest->BJBets[1].bet, ODBCQuery::MONEY);
					query->getData(17, &dest->BJBets[1].iBJBet);
                    query->getData(18, &dest->BJBets[1].numPlayerHands );
					query->getData(19, insState, 2 );
					    dest->BJBets[1].m_insuranceState = insState[0];

					// CSN-10085: three-hand blackjack
					query->getData(21, dest->BJBets[2].gid, BJ_GAMEID_SIZE);
                    query->getData(22, &dest->BJBets[2].bet, ODBCQuery::MONEY);
					query->getData(23, &dest->BJBets[2].iBJBet);
                    query->getData(24, &dest->BJBets[2].numPlayerHands );
					query->getData(25, insState, 2 );
					    dest->BJBets[2].m_insuranceState = insState[0];

				}
                else if (hasSaved==2)
				{
					result = 1;

                    // kharmon.  10-23-06.  #16151.  This is a newer saved game, where the 
                    // dealer cards aren't saved.  Use the original shoe settings to recreate
                    // the dealer cards.
                    dest->bHasOriginalShoe = true;      
					query->getData(2, &dest->maxBJBets);
					query->getData(3, &dest->nBJBets);
					query->getData(4, &dest->shue.seed);
					query->getData(5, &smallint);
					dest->shue.next = smallint;
					query->getData(6, &dest->numDecks);
					query->getData(7, &tinyint);
					dest->currentHand = tinyint;
					query->getData(8, &dest->currentBJBet);

					query->getData(9, &dest->originalShoe.seed);
					query->getData(10, &dest->originalShoe.next);					 

                    query->getData(11, dest->BJBets[0].gid, BJ_GAMEID_SIZE);
                    query->getData(12, &dest->BJBets[0].bet, ODBCQuery::MONEY);
					query->getData(13, &dest->BJBets[0].iBJBet);
                    query->getData(14, &dest->BJBets[0].numPlayerHands );
					query->getData(15, insState, 2 );
					    dest->BJBets[0].m_insuranceState = insState[0];

                    query->getData(16, dest->BJBets[1].gid, BJ_GAMEID_SIZE);
                    query->getData(17, &dest->BJBets[1].bet, ODBCQuery::MONEY);
					query->getData(18, &dest->BJBets[1].iBJBet);
                    query->getData(19, &dest->BJBets[1].numPlayerHands );
					query->getData(20, insState, 2 );
					    dest->BJBets[1].m_insuranceState = insState[0];              

					// CSN-10085: three-hand blackjack
					query->getData(21, dest->BJBets[2].gid, BJ_GAMEID_SIZE);
                    query->getData(22, &dest->BJBets[2].bet, ODBCQuery::MONEY);
					query->getData(23, &dest->BJBets[2].iBJBet);
                    query->getData(24, &dest->BJBets[2].numPlayerHands );
					query->getData(25, insState, 2 );
					    dest->BJBets[2].m_insuranceState = insState[0];

					query->getData(26, dest->dealerCards, MAXCARDS,	&dest->numDealerCards);

                    if(machid==PERFECT_PAIRS && query->getRow())
                    {
                        // kharmon.  02-13-07.  #16101.  If this is perfect pairs, there's be an extra row here
                        // to say what the result of the side bet was, even if the player didn't make a side bet.
                        // The side bet is resolved immediately after the deal, so the result is always known for 
                        // all saved games.
                        query->getData(1, &dest->BJBets[0].nPPSideBet, ODBCQuery::MONEY);
                        query->getData(2, &dest->BJBets[0].nPPSideBetPayout, ODBCQuery::MONEY);
                        query->getData(3, &dest->BJBets[0].nPPWinType);

                        query->getData(4, &dest->BJBets[1].nPPSideBet, ODBCQuery::MONEY);
                        query->getData(5, &dest->BJBets[1].nPPSideBetPayout, ODBCQuery::MONEY);
                        query->getData(6, &dest->BJBets[1].nPPWinType);

						query->getData(7, &dest->BJBets[2].nPPSideBet, ODBCQuery::MONEY);
                        query->getData(8, &dest->BJBets[2].nPPSideBetPayout, ODBCQuery::MONEY);
                        query->getData(9, &dest->BJBets[2].nPPWinType);
                    }
                }  
                else if(hasSaved==3)
                {
                    // kharmon.  05-04-07.  #19358.  Bad saved game.  Missing hands.  Return gamenum.                    
                    query->getData(2, dest->BJBets[0].gid, BJ_GAMEID_SIZE);
                    result=7;
                }
				else
                {
					result = 2;
                }
			}

			// player hands
			//
            int currentBet=0;
			while (query->getRow())
			{
				query->getData(1, &tinyint);
				which = tinyint;

					/*
						since this is a saved game
						the player must have already placed a bet so
						set the BJF_BET bit
						this is necessary because the initial save
						after deal doesn't record the actionBits
						since it previously assumed that the player
						hadn't executed any action other than deal
						there are blackjack style games that can
						actually begin with a deal before a bet is placed
						the game of PONTOON is an example of this
					*/

                if (which >= 0 && which < 3)
                {
                    totalHands++;
					if( ++numHands > dest->BJBets[currentBet].numPlayerHands )
                    {
                        numHands=1;
                        if( ++currentBet >= BJMAXBETS ) 
                        {
                            result = 6;
                            break;
                        }
                    }
                    if (!getSavedHand(query, &dest->BJBets[currentBet], which ))
					{
						result = 3;
						break;
					}
                }
				else	// too many...error
				{
					result = 3;
					break;
				}
			}

			if( result == 1 && dest->BJBets[0].numPlayerHands > 0 )
			{
				if( dest->BJBets[0].numPlayerHands+dest->BJBets[1].numPlayerHands+dest->BJBets[2].numPlayerHands == totalHands )
				{
                    uint8 nBets = 0;
                    result = 4;

                    if( dest->maxBJBets > BJMAXBETS ) result = 7;
                    if( dest->nBJBets > dest->maxBJBets ) result = 7;

                    for( int i=0; i<dest->nBJBets; i++ )
                    {
                        BJSavedGame::_BJBet *sBet = &(dest->BJBets[i]);
                        if( sBet->numPlayerHands>0 && *sBet->gid!='-' )
                        {
                            if( sBet->bet <= 0 ) result = 6; // there must be bet!!
                            nBets++;
                        }
                    }

                    if( dest->nBJBets != nBets ) result = 7;
				}
				else	// not enough or too many...error					
					result = 5;
			}
		}
		delete query;
	}
	delete conn;

	if (ok)
	{
		if (result == 2 || result == 4)	// no saved game or (game AND player ok)
		{
			*exists = (bool8)(result == 4);
			return NoError;
		}
		else
        {
			return BadSavedGame;
        }
	}
	else
		return ExecFailed;
}


int32
BJSQL::removeSavedGame(char*	gid)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJRemoveSavedGame ");
		query->addParam(gid, ODBCQuery::NOQUOTES);
		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
BJSQL::saveGame(const PID& pid, bool8 forMoney, BJSavedGame* src )
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		char insState[2];
		insState[1] = 0;
        
        query->define("exec pub_BJSaveGame ");
		query->addParam(src->maxBJBets );
		query->addParam(src->nBJBets);

	    query->addParam( src->BJBets[0].gid, ODBCQuery::NOQUOTES);
		insState[0] = src->BJBets[0].m_insuranceState;
 		query->addParam(insState);	

        // we may need to save 2 gid's if the player placed 2 bets!!
        if( src->nBJBets > 1  )
        {
		    query->addParam( src->BJBets[1].gid, ODBCQuery::NOQUOTES);
		    insState[0] = src->BJBets[1].m_insuranceState;
 		    query->addParam(insState);	
       }
        else 
        {
		    query->addParam( "-1", ODBCQuery::NOQUOTES);
 		    query->addParam("");	
        }
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(src->numDecks);
		query->addParam((int32)src->shue.seed);
		query->addParam(src->shue.next);

		query->addParam(src->currentBJBet);
		query->addParam(src->currentHand);

        // kharmon.  10-23-06.  #16151.  Save the original seed values so that we 
        // can use them to restore the dealer cards.
        query->addParam((int32)src->originalShoe.seed); 
        query->addParam(src->originalShoe.next);

		// cguerra. CSN-10085: three-hand blackjack
		// we may need to save 3 gid's if the player placed 3 bets!!
        if( src->nBJBets > 2  )
        {
		    query->addParam( src->BJBets[2].gid, ODBCQuery::NOQUOTES);
		    insState[0] = src->BJBets[2].m_insuranceState;
 		    query->addParam(insState);	
       }
        else 
        {
		    query->addParam( "-1", ODBCQuery::NOQUOTES);
 		    query->addParam("");	
        }

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}


int32
BJSQL::getForcedHands
(
	char*	pForcedHandDealer,
	char*	pForcedHandPlayer,
	int32	nBytesPerHand
)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJGetForcedHands ");

		if (query->exec())
		{
			if (query->getRow())
				query->getData( 1, pForcedHandDealer, nBytesPerHand );
			if (query->getRow())
				query->getData( 1, pForcedHandPlayer, nBytesPerHand );
			ok = true;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
BJSQL::resetSavedGame( char *gid )
{
	ODBCConnection* conn;
	ODBCQuery* query;
	int32 error;

	conn = getConn();
	if (!conn)
		return NoConnection;

	error = ExecFailed;
	query = conn->query();
	if (query)
	{
		query->define("exec pub_BJInitSavedGames ");
		if( gid )
			query->addParam(gid, ODBCQuery::NOQUOTES);

		if (query->exec())
			error = NoError;

		delete query;
	}
	delete conn;

	return error;
}